﻿using System;
using System.Collections.ObjectModel;
using System.Drawing;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using BLL.Model;
using BLL.Utils;
using CloudClipboardSync.MvvmFw;
using CloudClipboardSync.Utils;
using CloudClipboardSync.Windows;
using DAL.Clipboard;
using Hardcodet.Wpf.TaskbarNotification;

namespace CloudClipboardSync.Model
{
    public class ProgramData : MvvmBase, IClipboardHistoryManager
    {
        private readonly AutoStartHelper autoStartHelper = new AutoStartHelper();
        private readonly LoginManager loginManager = new LoginManager();
        private readonly SingleInstance singleInstance = new SingleInstance("cloudClipboardSync");
        private LoginWindow loginWindow;
        private MainWindow mainWindow;
        private SettingsWindow settingsWindow;
        private ClipboardSyncManager syncMan;

        public ProgramData()
        {
            if(!singleInstance.OwnsMutex)
                Environment.Exit(0);

            Instance = this;

            ClipboardHistory = new ObservableCollection<ClipboardContent>();

            this.OnPropertyChanged(x => x.SelectedClipboard, () => OnSelectedClipboardChanged(SelectedClipboard));

            Action<bool> loginAction = isNew =>
            {
                LoginWindowModel.UsernameIsEmpty = String.IsNullOrWhiteSpace(LoginWindowModel.Username);
                if (LoginWindowModel.UsernameIsEmpty) return;

                loginManager.Login(LoginWindowModel.Username ?? "", LoginWindowModel.Password ?? "", isNew);
                LoginWindowModel.LoginError = !loginManager.IsLoggedIn;

                if (loginManager.IsLoggedIn && loginWindow != null) loginWindow.Close();

                CheckLogin();
            };

            LoginWindowModel = new LoginWindowModel
            {
                LoginCommand = new DelegateCommand(delegate { loginAction(false); }), 
                RegisterCommand = new DelegateCommand(delegate { loginAction(true); })
            };

            ShowContextMenuCommand = new DelegateCommand(x => App.SystrayIcon.ShowContextMenu(App.SystrayIcon.LastClickPosition));
            ExitCommand = new DelegateCommand(x => Application.Current.Shutdown());
            OpenProgramCommand = new DelegateCommand(x => OpenProgram());
            ShowSettingsWindowCommand = new DelegateCommand(delegate { ShowWindow(settingsWindow, x => settingsWindow = x); });
            ClearClipboardCommand = new DelegateCommand(x => syncMan.ClearClipboard());

            SettingWindowOkCommand = new DelegateCommand(delegate
            {
                loginManager.SaveProfile();
                settingsWindow.Close();
            });
        }

        public static ProgramData Instance { get; protected set; }

        public ICommand OpenProgramCommand { get; private set; }
        public ICommand ShowSettingsWindowCommand { get; private set; }
        public ICommand ExitCommand { get; private set; }
        public ICommand ShowContextMenuCommand { get; private set; }
        public ICommand ClearClipboardCommand { get; private set; }

        public ICommand SettingWindowOkCommand { get; private set; }

        public LoginWindowModel LoginWindowModel { get; protected set; }

        public ClipboardContent SelectedClipboard { get; set; }

        public bool AutoStart
        {
            get { return autoStartHelper.IsEnabled; }
            set { autoStartHelper.IsEnabled = value; }
        }

        public bool IsLoggedIn { get; private set; }
        public Profile CurrentProfile { get { return loginManager.ProfileManager.Profile; } }

        #region IClipboardHistoryManager Members

        public ObservableCollection<ClipboardContent> ClipboardHistory { get; private set; }
        public event Action<ClipboardContent> OnSelectedClipboardChanged;

        public void AddNewItem(ClipboardContent content)
        {
            ClipboardHistory.Insert(0, content);
            SelectedClipboard = content;
        }

        public void ClipboardChangeAction(Action action)
        {
            GuiTools.RunOnGuiThread(action);
        }

        #endregion

        private void ShowWindow<T>(T wnd, Action<T> setter) where T: Window, new()
        {
            if (wnd != null)
                wnd.Activate();
            else
            {
                wnd = new T();
                setter(wnd);
                wnd.Closed += delegate { setter(null); };
                wnd.Show();
            }            
        }

        public void OpenProgram()
        {
            if (loginManager.IsLoggedIn)
                ShowWindow(mainWindow, x => mainWindow = x);
            else
                ShowWindow(loginWindow, x => loginWindow = x);            
        }

        public void CheckLogin()
        {
            IsLoggedIn = loginManager.IsLoggedIn;
            if (loginManager.IsLoggedIn)
            {
                syncMan = new ClipboardSyncManager(this, loginManager.ProfileManager);
                syncMan.OnClipboardChanged += () => App.SystrayIcon.ShowBalloonTip("Your clipboard has been changed!", "Click here to view the changes", BalloonIcon.Info);
                syncMan.EnableEvents();
                syncMan.LoadProfileContents();
            }

            OpenProgram();            
        }

        public void OnApplicationStarted()
        {
            var icon = Application.GetResourceStream(new Uri("pack://application:,,,/Images/icon.ico")); 
            App.SystrayIcon.Icon = icon != null ? new Icon(icon.Stream) : null;
            App.SystrayIcon.Visibility = Visibility.Visible;
            App.SystrayIcon.TrayBalloonTipClicked += delegate { OpenProgram(); };

            LoginWindowModel.Users = loginManager.GetUserProfiles();
            loginManager.TryAutoLogin();
            CheckLogin();
        }
    }
}
